import router from '@/router'
import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'
import { Message } from 'element-ui'
import { Method } from './method'

axios.defaults.withCredentials = true

axios.interceptors.response.use(
  response => {
    return response
  },
  err => {
    return Promise.reject(err)
  }
)

interface RequestConfig extends AxiosRequestConfig {
  type?: string
  body?: any
  hideLoading?: boolean
  hideMsg?: boolean
  requestByUrl?: boolean
  credentials?: string
  mode?: string
  baseURL?: string
  fullResponse?: boolean
  notToLogin?: boolean // 不跳转，默认跳转
}

export interface IResponse {
  errCode: number
  errorCode?: string
  data?: any
  msg?: string
}

export default function request(config: RequestConfig): Promise<any> {
  return new Promise((resolve, reject) => {
    const defaultHeaders = {
      'Content-Type': 'application/json;charset=UTF-8',
      Accept: '*/*',
      type: 'apply',
    }
    const { method, body, headers, mode, baseURL, notToLogin } = config
    let { url = '' } = config
    if (!url || typeof url !== 'string') {
      return
    }
    const newBaseURL = baseURL || ''
    const requestConf: RequestConfig = {
      baseURL: newBaseURL,
      method,
      // responseType: type || 'json',
      credentials: 'include',
      mode: mode || 'same-origin',
      headers: Object.assign(defaultHeaders, headers),
      withCredentials: true,
      maxRedirects: 5,
    }
    const middle = url.lastIndexOf('?')
    if (method === Method.GET) {
      const len = url.length - 1
      if (middle > -1 && middle === len) {
        url = url.substring(0, middle)
      }
      if (middle === -1) {
        url = `${url}?`
      }
      if (typeof body === 'object' && body !== null) {
        url += JSON.stringify(body)
      }
      if (typeof body === 'string') {
        url += body
      }
      requestConf.url = `${url}&t=${new Date().getTime()}`
      requestConf.body = body
    } else {
      requestConf.url = url
      requestConf.body = body
    }
    requestConf.data =
      typeof requestConf.body === 'string'
        ? requestConf.body
        : JSON.stringify(requestConf.body)
    axios(requestConf).then(
      (response: AxiosResponse) => {
        // 登出接口
        // 非 200 错误
        if (response.status !== 200) {
          Message.error('网络错误')
          reject('网络错误')

          return
        }

        // 返回没任何数据
        const { data } = response
        if (!data) {
          Message.error('数据异常')
          reject('数据异常')

          return
        }
        if (data.errorCode && data.errorCode === 'LOGIN_INVALID') {
          reject(data.errorCode)
          if (!notToLogin) {
            // 默认跳转，首页不跳转
            const invalidateMsg = document.getElementsByClassName(
              'invalidate'
            ) as HTMLCollection
            if (!invalidateMsg || invalidateMsg.length === 0) {
              // 保证仅有一个登录失效提示
              Message({
                type: 'error',
                customClass: 'invalidate',
                message: `${data.msg || '登录失效'}`,
              })
            }
            router.push({ name: 'homepage', query: { login: 'true' } })
          }

          return
        }

        // 支付超时特殊处理
        if (data.errorCode && data.errorCode === 'PAY_ORDER_CANCEL') {
          Message.error(data.msg || '')
          reject(data)

          return
        }
        // 业务异常
        if (data.errCode !== 0) {
          Message.error(data.msg || '')
          reject(data.msg)

          return
        }
        // 登录接口登录成功 返回token
        // 正常情况
        resolve(data)
      },
      (err: AxiosError) => {
        Message.error('网络错误')
        reject('网络错误')
      }
    )
  })
}
